package nancal.mp.db.mongo.entity.dev

import com.fasterxml.jackson.annotation.JsonIgnore
import nbcp.base.comm.StringMap
import nbcp.base.db.annotation.Cn
import nbcp.base.db.annotation.DbEntityGroup
import nbcp.base.extend.HasValue
import nbcp.base.extend.IsIn
import nbcp.base.extend.IsInItems
import nbcp.base.model.BaseMarkEntity
import nbcp.myoql.db.enums.RdbTypeEnum
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.data.mongodb.core.mapping.Document
import javax.sql.DataSource

@Cn("关系型数据连接")
@Document
@DbEntityGroup("dev")
data class DbConnection(
    @Cn("名称") var name: String = "",
    @Cn("数据库类型") var type: RdbTypeEnum? = null,
    @Cn("Ip") var host: String = "",
    @Cn("端口") var port: Int = 0,
    @Cn("用户名") var userName: String = "",
    @Cn("密码") var password: String = "",
    @Cn("数据库名") var dbName: String = "",
    var code: String = "",
    @Cn("备注") var remark: String = "",
    @Cn("组定义, key=table,value=组") var groupMap: StringMap = StringMap()
) : BaseMarkEntity() {

    /**
     * jdbc:mariadb://${db.host}:${db.port}/${db.dbName}?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false
     * jdbc:sqlserver://localhost:1433;databaseName=AdventureWorks;integratedSecurity=true;encrypt=true;trustServerCertificate=true
     * jdbc:oracle:thin:@localhost:1521:orcl
     */
    @JsonIgnore
    fun getJdbcUri(): String {
        if (port <= 0) {
            return "";
        }

        var querys = StringMap()

        if (type == RdbTypeEnum.sqlserver) {
            querys.put("databaseName", dbName)
            querys.put("integratedSecurity", "true")
            querys.put("encrypt", "true")
            querys.put("trustServerCertificate", "true")

            var ret = "jdbc:${
                type.toString().lowercase().replace("_", "")
            }://${host}:${port};${querys.map { it.key + "=" + it.value }.joinToString(";")}";

            return ret;
        } else if (type == RdbTypeEnum.oracle) {
            return "jdbc:oracle:thin:@//${host}:${port}/${dbName}"
        } else if (type == RdbTypeEnum.sqlite) {
            return "jdbc:sqlite:${dbName}"
        } else if (type.IsInItems(RdbTypeEnum.mysql, RdbTypeEnum.mariadb)) {
            if (userName.HasValue) {
                querys.put("user", userName)
            }

            if (password.HasValue) {
                querys.put("password", password)
            }

            querys.put("useUnicode", "true")
            querys.put("characterEncoding", "utf-8")
            querys.put("useSSL", "false")
            querys.put("serverTimezone", "Asia/Shanghai")
        } else if (type == RdbTypeEnum.postgresql) {
            querys.put("binaryTransfer", "false")
            querys.put("forceBinary", "false")
            querys.put("reWriteBatchedInserts", "true")
        }

        var ret = "jdbc:${
            type.toString().lowercase().replace("_", "")
        }://${host}:${port}/${dbName}?${querys.map { it.key + "=" + it.value }.joinToString("&")}";

        return ret;
    }

    @JsonIgnore
    fun getDataSource(): DataSource {
        return DataSourceBuilder
            .create()
            .type(com.zaxxer.hikari.HikariDataSource::class.java)
            .url(getJdbcUri())
            .username(userName)
            .password(password)
            .build()

    }
}